import crypto from 'crypto';
import { config } from '../config/env.js';
import { logger } from './logger.js';

// 从配置中获取加密密钥和向量
const AES_KEY = config.app.aesKey || 'Shif0ne@Product~';
const AES_IV = config.app.aesIv || 'ZYpq%kVPSYH8h@1q';

/**
 * AES 加密工具类
 */
export class Encrypt {
  private static readonly ALGORITHM = 'aes-256-cbc';
  private static readonly KEY_LENGTH = 32; // AES-256 需要 32 字节的密钥
  private static readonly IV_LENGTH = 16; // AES-CBC 需要 16 字节的初始化向量

  /**
   * 生成固定长度的密钥
   * @param key 原始密钥
   * @returns 固定长度的密钥
   */
  private static normalizeKey(key: string): Buffer {
    const hash = crypto.createHash('sha256').update(key).digest();
    return Buffer.from(hash).subarray(0, this.KEY_LENGTH);
  }

  /**
   * 生成固定长度的初始化向量
   * @param iv 原始向量
   * @returns 固定长度的向量
   */
  private static normalizeIV(iv: string): Buffer {
    const hash = crypto.createHash('md5').update(iv).digest();
    return Buffer.from(hash).subarray(0, this.IV_LENGTH);
  }

  /**
   * 加密字符串或 Buffer
   * @param data 要加密的数据
   * @param customKey 可选的自定义密钥
   * @param customIv 可选的自定义向量
   * @returns 加密后的字符串（十六进制编码）
   */
  public static encrypt(data: string | Buffer, customKey?: string, customIv?: string): string {
    try {
      const key = this.normalizeKey(customKey || AES_KEY);
      const iv = this.normalizeIV(customIv || AES_IV);
      const cipher = crypto.createCipheriv(this.ALGORITHM, key, iv);

      const inputData = Buffer.isBuffer(data) ? data : Buffer.from(data, 'utf8');
      const encrypted = Buffer.concat([cipher.update(inputData), cipher.final()]);

      return encrypted.toString('hex');
    } catch (error) {
      logger.error(`加密失败: ${error instanceof Error ? error.message : String(error)}`);
      return '';
    }
  }

  /**
   * 解密字符串
   * @param encryptedData 加密后的字符串（十六进制编码）
   * @param customKey 可选的自定义密钥
   * @param customIv 可选的自定义向量
   * @returns 解密后的字符串
   */
  public static decrypt(encryptedData: string, customKey?: string, customIv?: string): string {
    try {
      const key = this.normalizeKey(customKey || AES_KEY);
      const iv = this.normalizeIV(customIv || AES_IV);
      const decipher = crypto.createDecipheriv(this.ALGORITHM, key, iv);

      const encrypted = Buffer.from(encryptedData, 'hex');
      const decrypted = Buffer.concat([decipher.update(encrypted), decipher.final()]);

      return decrypted.toString('utf8');
    } catch (error) {
      logger.error(`解密失败: ${error instanceof Error ? error.message : String(error)}`);
      return '';
    }
  }

  /**
   * 解密为 Buffer
   * @param encryptedData 加密后的字符串（十六进制编码）
   * @param customKey 可选的自定义密钥
   * @param customIv 可选的自定义向量
   * @returns 解密后的 Buffer
   */
  public static decryptToBuffer(
    encryptedData: string,
    customKey?: string,
    customIv?: string
  ): Buffer {
    try {
      const key = this.normalizeKey(customKey || AES_KEY);
      const iv = this.normalizeIV(customIv || AES_IV);
      const decipher = crypto.createDecipheriv(this.ALGORITHM, key, iv);

      const encrypted = Buffer.from(encryptedData, 'hex');
      return Buffer.concat([decipher.update(encrypted), decipher.final()]);
    } catch (error) {
      logger.error(`解密失败: ${error instanceof Error ? error.message : String(error)}`);
      // 这里可以根据需要处理错误，例如返回一个空的 Buffer 或抛出自定义错误
      return Buffer.alloc(0); // Return an empty Buffer
    }
  }

  /**
   * 生成 MD5 哈希值
   * @param data 要生成哈希值的数据
   * @returns MD5 哈希值（十六进制编码）
   */
  public static md5(data: string | Buffer): string {
    try {
      const inputData = Buffer.isBuffer(data) ? data : Buffer.from(data, 'utf8');
      return crypto.createHash('md5').update(inputData).digest('hex');
    } catch (error) {
      logger.error(`生成 MD5 失败: ${error instanceof Error ? error.message : String(error)}`);
      return ''; // Return an empty strin
    }
  }
}
